package main

import "fmt"

func main() {
	/*
		位运算符：
			将数值，转化为二进制后，按位操作
		按位 &：
			对应位置的值如果都为 1 才为 1，有一个为 0 就为 0
		按位 |：
			对应位置的值如果都为 0 才为 0，有一个为 1 就为 1
		异或 ^：
			二元：a ^ b
				对应位置的值不同为 1，相同为 0
			一元：^ a
				按位取反：1——>0，0——>1
		位清空 &^：
			对于 a &^ b （其实就相当于：a & (^b)）
				对于 b 上的每个数值
				如果为 0，则取 a 对应位上的数值
				如果为 1，则结果位就取 0
		位移运算符：
		<<：按位左移，将 a 转化为二进制，向左移动 b 位，其实就是乘以 2 的 b 次方
			a << b
		>>：按位右移，将 a 转化为二进制，向右移动 b 位，相当于除以 2 的 b 次方
			a >> b

		*练习：
			有一堆数字，如果除了一个数字以外，其他数字都出现了两次，那么如何找到出现一次的数字？
	*/
	a := 60
	b := 13
	/*
		a: 60 0011 1100
		b: 13 0000 1101
		&  12 0000 1100
		|  61 0011 1101
		^  49 0011 0001
		&^ 48 0011 0000

		a : 0000 0000 ... 0011 1100
		^   1111 1111 ... 1100 0011
	*/
	fmt.Printf("a: %d, %b\n", a, a) // 60, 111100
	fmt.Printf("b: %d, %b\n", b, b) // 13, 1101

	res1 := a & b
	fmt.Println(res1) // 12

	res2 := a | b
	fmt.Println(res2) // 61

	res3 := a ^ b
	fmt.Println(res3) // 49

	res4 := a &^ b
	fmt.Println(res4) // 48

	res5 := ^a
	fmt.Println(res5) // -61

	c := 8
	/*
		c << 2
		c : ... 0000 1000
		        0010 0000
		c >> 2
				0000 0010
	*/
	res6 := c << 2
	fmt.Println(res6) // 32

	res7 := c >> 2
	fmt.Println(res7) // 2

	/*
		练习题：
			有一堆数字，如果除了一个数字以外，其他数字都出现了两次，那么如何找到出现一次的数字？
	*/
	num := [11]int{1, 2, 3, 4, 5, 5, 6, 4, 3, 2, 1}
	result := 0
	for _, a := range num {
		result ^= a
	}
	fmt.Println(result) // 6
}
